package cn.buk.qms.service;

import cn.buk.common.Constant;
import cn.buk.common.JsonResult;
import cn.buk.common.sc.CommonSearchCriteria;
import cn.buk.tms.dao.FlightOrderDao;
import cn.buk.tms.dao.ProductBoughtDao;
import cn.buk.tms.dao.ProductDao;
import cn.buk.tms.dao.UserDao;
import cn.buk.tms.dto.DtoLoginStatus;
import cn.buk.tms.dto.UserDto;
import cn.buk.tms.entity.config.EnterpriseConfig;
import cn.buk.tms.sc.SearchCustomerCriteria;
import cn.buk.tms.sc.SearchUserCriteria;
import cn.buk.tms.common.constant.TmsOrderConstant;
import cn.buk.tms.common.dto.CustomerDto;
import cn.buk.tms.dto.AddressDto;
import cn.buk.tms.dto.CustomerDetailDto;
import cn.buk.tms.dto.LoginInfoDto;
import cn.buk.tms.entity.misc.*;
import cn.buk.tms.factory.CustomerDtoFactory;
import cn.buk.common.util.CheckUtil;
import cn.buk.common.util.DateUtil;
import cn.buk.common.util.VerifyCodeUtil;
import com.alibaba.fastjson.JSON;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import static cn.buk.tms.entity.misc.User.SEARCH_MODE_EMPLOYEE;
import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * @author yfdai
 */
@Service
public class UserServiceImpl extends BaseAbstractService implements UserService {

  private static final Logger logger = LogManager.getLogger(UserServiceImpl.class);

  @Autowired
  private ProductDao productDao;

  @Autowired
  private ProductBoughtDao productBoughtDao;

  @Autowired
  private FlightOrderDao flightOrderDao;

  @Autowired
  private ProductService productService;


  @Override
  public List<User> search(int enterpriseId, SearchUserCriteria sc) {
    return userDao.search(enterpriseId, sc, SEARCH_MODE_EMPLOYEE);
  }

  /**
   * 查找用户（员工）
   */
  @Override
  public List<UserDto> searchUsers(int enterpriseId, SearchUserCriteria sc) {
    List<User> users = userDao.search(enterpriseId, sc, User.SEARCH_MODE_EMPLOYEE);

    List<UserDto> dtos = new ArrayList<>();
    for (User user : users) {
      UserDto dto = UserDto.createByUser(user);
      dtos.add(dto);

      if (user.getCustomerServiceGroupCode() != null) {
        GroupCustomerService g = enterpriseDao.searchGroupCustomerService(enterpriseId, user.getCustomerServiceGroupCode());
        if (g != null) {
          dto.setGroupCode(g.getGroupCode());
          dto.setGroupName(g.getGroupName());
        }
      }
    }

    return dtos;
  }

  /**
   * 查找会员用户
   */
  @Override
  public List<UserDto> searchMembers(final int enterpriseId, SearchUserCriteria sc) {
    List<User> users = userDao.search(enterpriseId, sc, User.SEARCH_MODE_MEMBER);

    List<UserDto> dtos = new ArrayList<>();
    for (User user : users) {
      UserDto dto = UserDto.createByUser(user);
      dtos.add(dto);

      // 获取企业名称
      Enterprise enterprise = enterpriseDao.getEnterpriseById(dto.getEnterpriseId());
      dto.setCorpName(enterprise.getName());

      // 获取openId(如果有）
      getBindWeixinUserInfo(enterpriseId, dto.getEnterpriseId(), dto.getId(), dto.getUsername(), dto.getWxsUsers());

    }

    return dtos;
  }

  @Override
  public User getUserById(int id) {
    return userDao.getUserById(id);
  }

  /**
   * 查看别人的信息, 检查是否有这个权限
   */
  @Override
  public User getUserById(final int enterpriseId, final int id) {
    if (enterpriseId == Enterprise.ENTERPRISE_PLATFORM_ADMINISTRATOR) {
      return getUserById(id);
    } else {
      return null;
    }
  }

  @Override
  public User getUserByUsername(String username) {
    try {
      return userDao.getUserByUsername(username);
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * 根据手机号查找用户信息
   *
   * @param ownerId  应用id
   * @param mobile   手机号
   * @param userType 用户类型
   */
  @Override
  public User getUserByMobile(final int ownerId, final String mobile, final int userType) {
    return userDao.getUserByMobile(ownerId, mobile, userType);
  }

  /**
   * 管理员添加新员工账号
   */
  @Override
  public int createUser(User user, final int enterpriseId, final String invitationCode) {

    boolean isExisted = userDao.isUsernameExisted(user.getUsername());
    if (isExisted) {
      return -10005;
    }

    if (enterpriseId < 1) {
      //新注册用户需要校验手机是否注册过
      isExisted = userDao.isMobileVerified(user.getMobileNo(), user.getUserType());
      if (isExisted) {
        return -10006;
      }
    }

    if (user.getExpireDate() == null) {
      Date defaultExpireDate = DateUtil.getCurDate();
      defaultExpireDate = DateUtil.addDays(defaultExpireDate, 1000);

      user.setExpireDate(defaultExpireDate);
    }

    if (enterpriseId > 0) {
      Enterprise enterprise = enterpriseDao.getEnterpriseById(enterpriseId);
      if (enterprise == null) {
        return -10004;
      }

      user.setEnterprise(enterprise);

      if (enterprise.getParentEnterprise() > 0) {
        user.setParentEnterprise(enterprise.getParentEnterprise());
      }
    }

    user.setMobilePhoneVerified("2");
    user.setSdAllowed(true);
    user.setCreateTime(DateUtil.getCurDate());

    return userDao.createUser(user, invitationCode);
  }

  // 管理员创建账号
  @Override
  @Secured({RoleInfo.ROLE_ADMIN})
  public int createUserByRoleAdmin(User user, int enterpriseId, String invitationCode) {
    return createUser(user, enterpriseId, invitationCode);
  }

  /**
   * 创建企业客户账户
   *
   * @param enterpriseId 当前登录用户的enterpriseId
   * @param c            新建的对象
   * @return 操作结果 >0 表示成功
   */
  @Override
  public int createCustomer(final int enterpriseId, final int userId, final String username,
                            Customer c) {
    User user = new User();
    user.setUsername("user_" + DateUtil.getCurDateTime().getTime());
    user.setEmpname(c.getVipName());

    Date defaultExpireDate = DateUtil.getCurDate();
    defaultExpireDate = DateUtil.addDays(defaultExpireDate, 10000);
    user.setExpireDate(defaultExpireDate);

    user.setCreateTime(DateUtil.getCurDate());
    user.setMd5Password(VerifyCodeUtil.MD5(User.DEFAULT_PASSWORD));
    user.setUserType(User.USER_TYPE_ENT); // 默认为企业客户

    c.setId(0);
    c.setStatus(0); // 新建用户默认为停用状态
    if (userId == enterpriseId) {
      c.setStatus(1); // 如果是根管理员，则为启用状态
    }

    try {
      int status = userDao.createTmcUser(enterpriseId, user, c);

      if (status > 0) {
        // 在EnterpriseBalance中生成记录
        enterpriseDao.getEnterpriseBalance(enterpriseId, user.getEnterprise().getId());

        String remark =
                "创建客户成功：" + username + "创建客户（" + c.getId() + ", " + c.getVipName() + ", " + c
                        .getCustomerCode() + ", " + c.getEnterpriseType() + ")资料成功，等待启用。";
        doSendAlert(enterpriseId, remark, null, EntDepartment.DEPT_ADMINISTRATOR);
      }

      return c.getId();
    } catch (RuntimeException ex) {
      logger.error(ex.getCause().getCause().getMessage());
      logger.error(ex.getMessage());
      return -100;
    }
  }

  @Override
  public int createOrUpdateCustomer(int enterpriseId, int userId, String username, Customer c) {
    if (c.getId() == 0) {
      return this.createCustomer(enterpriseId, userId, username, c);
    } else {
      return this.updateCustomer(enterpriseId, userId, username, c);
    }
  }

  /**
   * @return the userDao
   */
  public UserDao getUserDao() {
    return userDao;
  }

  /**
   * @param userDao the userDao to set
   */
  public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
  }

  /**
   * 修改密码
   */
  @Override
  public JsonResult updateUserPassword(final int enterpriseId, final int userId,
                                       final String username, final String currentPassword, final String newPassword,
                                       final String confirmPassword) {

    if (newPassword == null || newPassword.trim().length() == 0) {
      return JsonResult.createJsonResult(-1, "请输入新密码");
    }
    if (!newPassword.equalsIgnoreCase(confirmPassword)) {
      return JsonResult.createJsonResult(-2, "新密码和确认密码不匹配");
    }
    if (newPassword.equalsIgnoreCase(currentPassword)) {
      return JsonResult.createJsonResult(-3, "新密码和当前密码不能相同");
    }

    User user = userDao.getUserByUsername(username);
    if (user == null || user.getId() != userId || user.getEnterpriseId() != enterpriseId) {
      return JsonResult.createJsonResult(-4, "请检查用户名和当前密码");
    }

    final String currentPasswordMd5 = VerifyCodeUtil.MD5(currentPassword);

    if (user.getMd5Password() != null && !user.getMd5Password().equalsIgnoreCase(currentPasswordMd5)) {
      return JsonResult.createJsonResult(-5, "请检查用户名和当前密码");
    } else if (user.getMd5Password() == null && !user.getPassword().equalsIgnoreCase(currentPassword)) {
      return JsonResult.createJsonResult(-5, "请检查用户名和当前密码");
    }

    if (user.getPassword_locked() == 1) {
      return JsonResult.createJsonResult(-6, "该用户密码暂不允许修改");
    }

    final String newPasswordMd5 = VerifyCodeUtil.MD5(newPassword);

    int retCode = userDao.updateUserPassword(enterpriseId, userId, username, newPasswordMd5);

    return JsonResult.createJsonResult(retCode);
  }

  @Override
  public JsonResult checkIn(final int ownerId, final int enterpriseId, final int userId,
                            final String ip) {
    UserCheckIn uci = new UserCheckIn();
    uci.setUserId(userId);
    uci.setEnterpriseId(enterpriseId);
    uci.setIp(ip);
    uci.setCheckInDate(DateUtil.getCurDate());

    int checkInStatus = userDao.checkIn(uci);

    JsonResult jr = new JsonResult();
    if (checkInStatus == 100) {
      jr.setStatus("OK");
      //签到成功，判断连续签到成功次数
      int continueDays = 0;
      List<UserCheckIn> ucis = userDao.getTopFiveCheckIn(enterpriseId, 30);
      if (ucis.size() > 1) {
        Date oldDate = DateUtil.getCurDate();
        for (UserCheckIn uci1 : ucis) {
          if (uci1.getCheckInDate().compareTo(oldDate) == 0) {
            continueDays++;
            oldDate = DateUtil.addDays(oldDate, -1);
          } else {
            break;
          }
        }
      } else {
        continueDays = ucis.size();
      }

      userDao.incCheckInPrize(ownerId, enterpriseId, userId, continueDays);

      jr.setDesc("签到成功");
    } else {
      jr.setStatus("ER");

      if (checkInStatus == 2) {
        jr.setDesc("今天已经签到过了，明天再来哦。");
      }
    }

    return jr;
  }

  @Override
  public List<AmountHistory> searchTransactionHistory(int enterpriseId, CommonSearchCriteria sc) {
    return userDao.searchTransactionHistory(enterpriseId, sc);
  }

  @Override
  public void createLoginHistory(LoginHistory log) {
    userDao.createLoginHistory(log);
  }

  @Override
  public List<LoginHistory> searchHistory(int enterpriseId, String username,
                                          CommonSearchCriteria sc) {
    return userDao.searchHistory(enterpriseId, username, sc);
  }

  /**
   * 搜索余额
   */
  @Override
  public UserDto searchEnterpriseBalance(final int enterpriseId) {
    Enterprise enterprise = userDao.getEnterpriseById(enterpriseId);

    final int authorizer = enterprise.getParentEnterprise() > 0 ? enterprise.getParentEnterprise()
            : Enterprise.ENTERPRISE_PLATFORM_ADMINISTRATOR;

    EnterpriseBalance entBalance = enterpriseDao.getEnterpriseBalance(authorizer, enterpriseId);

    UserDto userDto = new UserDto();

    userDto.setEnterpriseName(enterprise.getName());
    userDto.setBalance(entBalance.getBitcoinBalance());
    userDto.setCashBalance(entBalance.getCashBalance());
    userDto.setCreditLimit(entBalance.getCreditLimit());

    userDto.setFrozenBalance(entBalance.getFrozenBalance());

    return userDto;
  }

  /**
   * 将登录信息保存到redis
   */
  @Override
  public void saveToken(DtoLoginStatus dtoLoginStatus) {
    String key = "token:" + dtoLoginStatus.getToken();
    String value = JSON.toJSONString(dtoLoginStatus);
    logger.debug(key);
    logger.debug(value);

    redisDao.setAndExpire(key, value.getBytes(UTF_8), 60 * 60 * 24 * 7);
  }

  /**
   * 搜索的客户概要信息
   */
  @Override
  public List<CustomerDto> searchCustomers(int enterpriseId, int userId,
                                           SearchCustomerCriteria sc) {

    // 当前用户允许查看的企业客户ID
    List<Integer> allowedCustomerIds = searchAllowedCustomerIds(enterpriseId, userId);

//        sc.setStatus(1); // 启用状态
    List<Customer> customers = customerDao.searchCustomers(enterpriseId, sc, allowedCustomerIds);

    List<CustomerDto> dtos = new ArrayList<>();

    for (Customer info : customers) {
      CustomerDto dto = CustomerDtoFactory.createByCustomer(info);


      dtos.add(dto);
    }

    return dtos;
  }

  /**
   * 查找客户资料
   */
  @Override
  @Secured({RoleInfo.ROLE_OPERATOR, RoleInfo.ROLE_TICKETER, RoleInfo.ROLE_SALE_MAN,
          RoleInfo.ROLE_SUPERVISOR, RoleInfo.ROLE_DATA_ADMIN, RoleInfo.ROLE_ADMIN})
  public List<CustomerDetailDto> searchCustomerDetails(final int enterpriseId, int userId, final SearchCustomerCriteria sc) {
    List<Integer> ids = searchAllowedCustomerIds(enterpriseId, userId);
    List<Customer> customers = customerDao.searchCustomers(enterpriseId, sc, ids);

    return convertCustomers2Dtos(customers);
  }

  @Override
  public List<CustomerDetailDto> searchCustomerByCustomerEnterpriseId(int enterpriseId,
                                                                      int customerEnterpriseId) {
    List<Customer> customers = customerDao
            .searchCustomerByCustomerEnterpriseId(enterpriseId, customerEnterpriseId);

    return convertCustomers2Dtos(customers);
  }

  private List<CustomerDetailDto> convertCustomers2Dtos(List<Customer> customers) {
    List<CustomerDetailDto> dtos = new ArrayList<>();
    for (Customer c : customers) {
      dtos.add(convertCustomersDto(c));
    }

    return dtos;
  }

  private CustomerDetailDto convertCustomersDto(Customer c) {
    CustomerDetailDto dto = new CustomerDetailDto();
    BeanUtils.copyProperties(c, dto);


    if (c.getCustomerServiceGroupCode() != null) {
      //获取分组名称
      GroupCustomerService g = enterpriseDao.searchGroupCustomerService(c.getEnterpriseId(), c.getCustomerServiceGroupCode());
      if (g != null) {
        dto.setGroupCode(g.getGroupCode());
        dto.setGroupName(g.getGroupName());
      }
    }

    if (c.getTemplateCode() != null) {
      //获取模板名称
      CustomerServiceTemplate tpl = enterpriseDao.searchCustomerServiceTemplate(c.getEnterpriseId(), c.getTemplateCode());
      if (tpl != null) {
        dto.setTemplateCode(tpl.getTemplateCode());
        dto.setTemplateName(tpl.getTemplateName());
      }
    }

    //获取结算单报表模板名称
    if (c.getReportTemplateId() > 0) {
      List<ReportTemplateInfo> tpls = enterpriseDao.searchReportTemplates(0);
      for (ReportTemplateInfo tpl : tpls) {
        if (tpl.getId() == c.getReportTemplateId()) {
          dto.setReportTemplateId(c.getReportTemplateId());
          dto.setReportTemplateName(tpl.getName());
        }
      }
    }

    return dto;
  }

  @Override
  public CustomerDetailDto getCustomerById(final int enterpriseId, final int id) {
    Customer c = customerDao.getCustomerById(id);
    if (c == null || c.getEnterpriseId() != enterpriseId) {
      return null;
    }

    CustomerDetailDto dto = convertCustomersDto(c);

    //获取登录信息
    if (dto.getCustomerEnterpriseId() > 0) {
      User user = userDao.getUserById(dto.getCustomerEnterpriseId());
      if (user != null) {
        LoginInfoDto loginInfo = new LoginInfoDto();
        loginInfo.setUsername(user.getUsername());
        loginInfo.setId(user.getId());
        loginInfo.setStatus(user.getStatus());
        loginInfo.setEtermUsername(user.getEtermUsername());

        dto.setLoginInfo(loginInfo);

        //获取EOTMS URL
        String url = doGetEntCfg(enterpriseId, EnterpriseConfig.EOTMS_URL);
        if (url == null || url.trim().length() == 0) {
          url = doGetEntCfg(0, EnterpriseConfig.EOTMS_URL);
        }

        loginInfo.setEotmsUrl(url);
      }
    }

    //获取邮寄地址
    List<CustomerAddress> addresses = customerDao.searchCustomerAddresses(enterpriseId, c.getId());
    if (addresses.isEmpty()) {
      AddressDto addressDto = new AddressDto();
      dto.getAddresses().add(addressDto);

      addressDto.setAlias("默认");
      addressDto.setLinkman(dto.getLinkman());
      addressDto.setMobile(dto.getMobile());
      addressDto.setEmail(dto.getEmail());
      addressDto.setPhone(dto.getPhone());
      addressDto.setPostcode(dto.getPostCode());
      addressDto.setAddress(dto.getAddress());

      if (dto.getMobile() == null || !CheckUtil.isMobileNo(dto.getMobile())) {
        if (dto.getPhone() != null && CheckUtil.isMobileNo(dto.getPhone())) {
          addressDto.setMobile(dto.getPhone());
        }
      }
    }

    return dto;
  }

  @Override
  @Secured({RoleInfo.ROLE_ADMIN})
  public int updateUser(int enterpriseId, int id, String empname, String email, String mobileNo,
                        String etermUsername,
                        String position, Integer[] deptIds, int status) {
    return userDao
            .updateUser(enterpriseId, id, empname, email, mobileNo, etermUsername, position, deptIds,
                    status);
  }

  @Override
  public JsonResult searchItineraryInfo(final int enterpriseId) {

    Product product = productDao.getByCode(Product.ITINERARY_PRINT_CODE);
    if (product == null) {
      return JsonResult.createJsonResult(-10000, "系统参数错误");
    }

    ProductBought boughtInfo = productBoughtDao.getByProductId(product.getId(), enterpriseId);

    if (boughtInfo == null) {
      return JsonResult.createJsonResult(-1, "没有购买记录");
    }

    JsonResult jsonResult = JsonResult.createJsonResult(1);
    jsonResult.setAttach(DateUtil.formatDate(boughtInfo.getEndTime(), "yyyy-MM-dd"));

    return jsonResult;
  }

  @Override
  public JsonResult buyItinerary(final int enterpriseId) {
    //1. 检查付费购买的有效期是否已到
    Product product = productDao.getByCode(Product.ITINERARY_PRINT_CODE);
    if (product == null) {
      return JsonResult.createJsonResult(-1, "系统参数错误");
    }

    productBoughtDao.getByProductId(product.getId(), enterpriseId);

    //未购买,或者已过期需要重新购买
    //2.设定的监控政策数是多少, 按照其值进行计费
    final int buyQuantity = 1;
    int retCode = productService
            .buyProduct(enterpriseId, Product.ITINERARY_PRINT_CODE, buyQuantity, 30);
    if (retCode == 100) {
      //购买成功
      return JsonResult.createJsonResult(100, "购买成功");
    } else if (retCode == 1) {
      //余额不足
      return JsonResult.createJsonResult(-2, "余额不足");
    } else {
      logger.error(retCode);
    }

    return JsonResult.createJsonResult(-3, "其它错误");
  }

  /**
   * 修改客户资料
   */
  @Override
  @Secured({RoleInfo.ROLE_ADMIN})
  public int updateCustomer(final int enterpriseId, final int userId, final String username,
                            Customer c) {
    if (c.getId() < 1) {
      throw new RuntimeException("cannot execute update operation for Customer which id is 0.");
    }
    Customer oldCustomer = customerDao.getCustomerById(c.getId());
    if (oldCustomer == null || oldCustomer.getEnterpriseId() != enterpriseId) {
      throw new RuntimeException("Customer(" + c.getId() + ") is not existed.");
    }

    //逐项赋值，防止新增加的字段，由于页面上没增加，而被覆盖
    //保存修改时带来的客服服务分组服务代码
    oldCustomer.setCustomerServiceGroupCode(c.getGroupCode());

    oldCustomer.setCustomerCode(c.getCustomerCode());
    oldCustomer.setVipName(c.getVipName());
    oldCustomer.setFullName(c.getFullName());
    oldCustomer.setEnterpriseType(c.getEnterpriseType());
    oldCustomer.setPinyin(c.getPinyin());
    oldCustomer.setServiceItem(c.getServiceItem());
    oldCustomer.setAgreementBeginDate(c.getAgreementBeginDate());
    oldCustomer.setAgreementEndDate(c.getAgreementEndDate());
    oldCustomer.setApprovalType(c.getApprovalType());
    oldCustomer.setApprovalMode(c.getApprovalMode());
    oldCustomer.setApprovalTicket(c.getApprovalTicket());
    oldCustomer.setContractLinkPhone(c.getContractLinkPhone());
    oldCustomer.setContractLinkman(c.getContractLinkman());
    oldCustomer.setCustomerMaintainer(c.getCustomerMaintainer());
    oldCustomer.setEmail(c.getEmail());
    oldCustomer.setFax(c.getFax());
    oldCustomer.setLinkman(c.getLinkman());
    oldCustomer.setAddress(c.getAddress());
    oldCustomer.setMobile(c.getMobile());
    oldCustomer.setPhone(c.getPhone());
    oldCustomer.setPostCode(c.getPostCode());
    oldCustomer.setRemark(c.getRemark());
    oldCustomer.setSalesStaff(c.getSalesStaff());
    oldCustomer.setSettlementType(c.getSettlementType());
    oldCustomer.setSettlementMode(c.getSettlementMode());
    oldCustomer.setSettlementPeriod(c.getSettlementPeriod());
    oldCustomer.setItineraryType(c.getItineraryType());
    oldCustomer.setTestMode(c.getTestMode());
    oldCustomer.setStatus(c.getStatus());


    int retCode = userDao.updateCustomer(oldCustomer);

    if (retCode > 0) {
      String remark = String.format("修改成功：%s修改客户（%d, %s, %s, %d, %d, %d)资料成功。", username, c.getId(), c.getVipName(),
              c.getCustomerCode(), c.getEnterpriseType(), c.getStatus(), c.getTestMode());
      doSendAlert(enterpriseId, remark, null, EntDepartment.DEPT_ADMINISTRATOR);
    }

    return retCode;
  }

  /**
   * 加载用户角色
   *
   * @param userId user id
   */
  @Override
  public Set<String> loadRolesByUserId(int userId) {
    return userDao.loadUserRoles(userId);
  }

  /**
   * 查找当前用户的权限
   */
  @Override
  public List<RolePrivilege> searchPrivileges(final int enterpriseId, final int userId) {
    List<RolePrivilege> rolePrivileges = userDao.searchPrivileges(enterpriseId, userId);

    if (rolePrivileges.isEmpty()) {
      //当前用户没有所属组，用默认角色和部门角色试试找找权限
      User user = userDao.getUserById(userId);
      for (EntDepartment d : user.getDepartments()) {
        if (d.getRole() != null && d.getRole().trim().length() > 0) {
          rolePrivileges.addAll(userDao.searchPrivilegesByRole(enterpriseId, d.getRole()));
        }
      }
    }

    //当前用户的角色
    Set<String> roles = userDao.loadUserRoles(userId);
    for (String roleName : roles) {
      RolePrivilege o = new RolePrivilege();
      o.setRole(roleName);
      rolePrivileges.add(o);
    }


    return rolePrivileges;
  }

  /**
   * 重置密码
   */
  @Override
  public int resetPassword(int userId, String newPassword) {
    final String newPasswordMd5 = VerifyCodeUtil.MD5(newPassword);

    return userDao.updateUserPassword(userId, newPasswordMd5);
  }

  @Override
  public List<Enterprise> searchCustomerTodo(int enterpriseId) {
    return userDao.searchCustomerTodo(enterpriseId);
  }


  /**
   * 根据绑定的企业微信userId查找用户
   */
  @Override
  public User getUserByWwUserId(int enterpriseId, String userid) {
    return userDao.getUserByWwUserId(enterpriseId, userid);
  }

  /**
   * 注册新租户的root账号
   *
   * @param user           用户注册信息
   * @param invitationCode 邀请码
   */
  @Override
  public JsonResult registerNewTenancyUser(User user, String invitationCode) {
    logger.info(
            "register:" + user.getUsername() + "," + user.getMobileNo() + "," + user.getEmail() + ","
                    + user.getEmpname());

    User u = userDao.getUserByUsername(user.getUsername());
    if (u != null) {
      return JsonResult.createJsonResult(-10005, "用户名已存在");
    }

    user.setUserType(User.USER_TYPE_PSG);

    //新注册用户需要校验手机是否注册过
    boolean isExisted = userDao.isMobileVerified(user.getMobileNo(), user.getUserType());
    if (isExisted) {
      return JsonResult.createJsonResult(-10006, "该手机号已被其它用户占用");
    }

    // 数据库中该字段为必须填写的
    if (user.getExpireDate() == null) {
      Date defaultExpireDate = DateUtil.getCurDate();
      defaultExpireDate = DateUtil.addDays(defaultExpireDate, 1000);

      user.setExpireDate(defaultExpireDate);
    }

    final String firstPassword = VerifyCodeUtil.getMobileVerifyCode(user.getMobileNo());
    user.setMd5Password(VerifyCodeUtil.MD5(firstPassword));

    user.setMobilePhoneVerified("2");
    user.setSdAllowed(true);
    user.setCreateTime(DateUtil.getCurDate());

    try {
      int retCode = userDao.createUser(user, invitationCode);

      final String smsContent = "用户名:" + user.getUsername() + " 密码:" + firstPassword;

      this.execSendSms(user.getMobileNo(), smsContent);

      return JsonResult.createJsonResult(retCode, smsContent);
    } catch (RuntimeException ex) {
      logger.error(ex.getMessage());
      return JsonResult.createJsonResult(-100, "保存时出现错误，可以试试注册别的用户名");
    }
  }

  /**
   * 重置用户密码
   */
  @Override
  @Secured({RoleInfo.ROLE_ADMIN})
  public JsonResult resetUserPassword(final int enterpriseId, final String username,
                                      final int userId, String newPassword) {
    if (newPassword == null || newPassword.trim().length() < 6
            || newPassword.trim().length() > 20) {
      return JsonResult.createJsonResult(-1, "密码的长度需要在6至20中间");
    }

    if (userId == enterpriseId) {
      doSendAlert(enterpriseId, username + "试图重置超级管理员的密码", null, EntDepartment.DEPT_ADMINISTRATOR);
      return JsonResult.createJsonResult(-2, "该用户的密码需自行修改");
    }

    final String md5Password = VerifyCodeUtil.MD5(newPassword);

    int retCode = userDao.resetUserPassword(enterpriseId, username, userId, md5Password);

    return JsonResult.createJsonResult(retCode);
  }

  @Override
  public int autoCreateUserByOpenId(final int ownerId, final String openid) {
    int enterpriseId = 0;
    UserBindWeixin ubw = userDao.getUserByOpenid(ownerId, openid);
    if (ubw != null) {
      enterpriseId = ubw.getEnterpriseId();
    } else {
      User user = new User();
      user.setRealname("");
      user.setMobileNo("");
      user.setUsername(User.getTemporaryUsername());
      user.setUserType(User.USER_TYPE_PSG);
      user.setMd5Password(VerifyCodeUtil.MD5(User.DEFAULT_PASSWORD));

      user.setParentEnterprise(ownerId);
      Date defaultExpireDate = DateUtil.getCurDate();
      defaultExpireDate = DateUtil.addDays(defaultExpireDate, 1000);

      user.setExpireDate(defaultExpireDate);

      user.setMobilePhoneVerified("0");
      user.setSdAllowed(true);
      user.setCreateTime(DateUtil.getCurDate());

      enterpriseId = userDao.createUser(user, null);

      // 和当前openid 绑定
      userDao.createUserBindWeixin(ownerId, openid, enterpriseId, enterpriseId, user.getUsername());
    }

    return enterpriseId;
  }

  @Override
  public void sendAlert(int enterpriseId, String username, String content) {
    LoginHistory h = new LoginHistory();
    h.setEnterpriseId(enterpriseId);
    h.setFunctionId(Constant.FUNCTION_SYSTEM_LOGIN);
    h.setUsername(username);
    h.setMemo(content);
    userDao.createLoginHistory(h);
    doSendAlert(enterpriseId, content, "Dai", 0);
  }

  @Override
  @Secured({RoleInfo.ROLE_ADMIN})
  public JsonResult disableUser(final int enterpriseId, final String username, final int userId) {

    if (userId == enterpriseId) {
      doSendAlert(enterpriseId, username + "试图禁用管理员", null, EntDepartment.DEPT_ADMINISTRATOR);
      return JsonResult.createJsonResult(-2, "");
    }

    int retCode = userDao.disableUser(enterpriseId, username, userId);

    return JsonResult.createJsonResult(retCode);
  }

  @Override
  public JsonResult enableUser(int enterpriseId, String username, int userId) {
    int retCode = userDao.enableUser(enterpriseId, username, userId);

    return JsonResult.createJsonResult(retCode);
  }

  @Override
  public JsonResult updateUserUsername(int enterpriseId, String username, int userId, String newUsername) {
    try {
      int retCode = userDao.updateUserUsername(enterpriseId, username, userId, newUsername);

      return JsonResult.createJsonResult(retCode);
    } catch (RuntimeException ex) {
      return JsonResult.createJsonResult(-100, ex.getMessage());
    }
  }

  @Override
  public JsonResult updateUserEtermUsername(int enterpriseId, String username, int userId, String etermUsername) {
    try {
      int retCode = userDao.updateUserEtermUsername(enterpriseId, username, userId, etermUsername.trim().toUpperCase());

      return JsonResult.createJsonResult(retCode);
    } catch (RuntimeException ex) {
      return JsonResult.createJsonResult(-100, ex.getMessage());
    }
  }

  @Override
  public JsonResult updateUserEmail(int enterpriseId, String username, int userId, String email) {
    try {
      int retCode = userDao.updateUserEmail(enterpriseId, username, userId, email);

      return JsonResult.createJsonResult(retCode);
    } catch (RuntimeException ex) {
      return JsonResult.createJsonResult(-100, ex.getMessage());
    }
  }

  @Override
  public JsonResult updateUserMobile(int enterpriseId, String username, int userId, String mobile) {
    try {
      int retCode = userDao.updateUserMobile(enterpriseId, username, userId, mobile);

      return JsonResult.createJsonResult(retCode);
    } catch (RuntimeException ex) {
      return JsonResult.createJsonResult(-100, ex.getMessage());
    }
  }

  @Override
  public List<User> searchUsersByMobile(String mobile) {
    return userDao.searchUsersByMobile(mobile);
  }

  @Override
  public UserDto searchUser(final int enterpriseId, final int id) {
    User user = userDao.getUserById(id);
    if (user == null || user.getEnterpriseId() != enterpriseId) {
      return null;
    }

    UserDto dto = UserDto.createByUser(user);

    if (user.getCustomerServiceGroupCode() != null) {
      GroupCustomerService g = enterpriseDao.searchGroupCustomerService(enterpriseId, user.getCustomerServiceGroupCode());
      if (g != null) {
        dto.setGroupCode(g.getGroupCode());
        dto.setGroupName(g.getGroupName());
      }
    }

    return dto;
  }

  @Override
  public void finishTaskCardMessage(final int enterpriseId, final String wwUserId, final String taskId,
                                    final String eventKey, final Long createTime) {
    TmsTaskLog log = new TmsTaskLog();
    log.setEnterpriseId(enterpriseId);
    log.setWwUserId(wwUserId);
    log.setTaskId(Integer.parseInt(taskId));
    log.setEventKey(eventKey);
    log.setProcessedTime(DateUtil.timestampToDate(createTime * 1000));

    int logId = userDao.createTmsTaskLog(log);

    TmsTask task = userDao.getTmsTaskById(Integer.parseInt(taskId));
    if (task != null && task.getOrderType() == TmsOrderConstant.FLIGHT_ORDER_CANCEL_REQUEST
            && task.getOrderId() > 0) {
      //机票订单的取消开票申请单
      User user = userDao.getUserByWwUserId(enterpriseId, wwUserId);
      if (user != null && "no".equalsIgnoreCase(eventKey)) {
        //拒绝
        flightOrderDao.denyCancelRequest(enterpriseId, user.getUsername(), task.getOrderId(), "拒绝(企业微信)订单取消");
      } else if (user != null && "yes".equalsIgnoreCase(eventKey)) {
        //批准
        flightOrderDao.agreeCancelRequest(enterpriseId, user.getUsername(), task.getOrderId(), "同意(企业微信)订单取消(" + task.getContent() + ")");
      }
    }

  }

  @Override
  public UserDto searchMemberDetail(int enterpriseId, int id) {
    var user = userDao.getUserById(id);
    if (user == null || user.getParentEnterprise() != enterpriseId) {
      return null;
    }

    UserDto dto = UserDto.createByUser(user);

    // 获取企业名称
    var enterprise = enterpriseDao.getEnterpriseById(dto.getEnterpriseId());
    dto.setCorpName(enterprise.getName());

    // 获取openId(如果有）
    getBindWeixinUserInfo(enterpriseId, dto.getEnterpriseId(), dto.getId(), dto.getUsername(), dto.getWxsUsers());


    return dto;
  }

  @Override
  public JsonResult unbindWeixinUser(int ownerId, int userId, String openId) {
    var userBindWeixin = userDao.getUserByOpenid(ownerId, openId);
    if (userBindWeixin == null || userBindWeixin.getUserId() != userId) {
      return JsonResult.createJsonResult(-1, "未找到相关信息");
    }


    int retCode = userDao.unbindWeixinUser(ownerId, openId);

    return JsonResult.createJsonResult(retCode);
  }

  @Override
  public JsonResult bindWeixinUser(int ownerId, int userId, String openId) {
    var userBindWeixin = userDao.getUserByOpenid(ownerId, openId);
    if (userBindWeixin != null) {
      return JsonResult.createJsonResult(-1, "该微信公众号用户已绑定" + userBindWeixin.getUsername());
    }

    var user = userDao.getUserById(userId);
    if (user== null || user.getParentEnterprise() != ownerId) {
      return JsonResult.createJsonResult(-2, "该用户不存在");
    }

    int retCode = userDao.createUserBindWeixin(ownerId, openId, user.getEnterpriseId(), user.getId(), user.getUsername());

    return JsonResult.createJsonResult(retCode);
  }

  @Override
  public List<User> searchUsersByDepartment(int enterpriseId, int deptId, CommonSearchCriteria sc) {
    return userDao.searchUsersByDepartment(enterpriseId, deptId);
  }
}
